#!/usr/bin/env python
#
'''
Created on 2009-3-19

@author: Wang_Yuan
'''

import wx

import re

import core
from ExampleEditorPanel_xrc import *

class ExampleEditorPanel(xrcExampleEditorPanel):
    '''
    Example Editor
    '''


    def __init__(self, parent):
        '''
        Constructor
        '''
        xrcExampleEditorPanel.__init__(self, parent)
        self.__initData()
        self.__initCtrls()
        self.__initEvents()
        
    def __initData(self):
        self.example = core.WordExample()
        self.mark = [-1, -1]
        self.prelen = len(self.exampleText.GetValue())
        self.settingExStyle = False
        
        self.exampleStyle = wx.TextAttr()
        self.exampleText.GetStyle(2, self.exampleStyle)
        
    def __initCtrls(self):
        self.exampleText.SetFocus()
        self.setFormatErrorStyle(None)
        
    def __initEvents(self):
        self.ExampleFormatErrorBar.Bind(wx.EVT_LEFT_DOWN, self.OnLeft_down_ExampleFormatErrorBar)
        
    def OnLeft_down_ExampleFormatErrorBar(self, evt):
        message = u'''
About example format
-----------------------------
Every example in this application must have a keyword. 
A keyword means the word the example for. 
When the system build an examination, the keyword will be left blank 
and the user should fill it in. 

Maybe you want to ask why not use the original word. 
The answer is there are so many states for one word, and the computer 
is not good at English grammar, so this need manual operation. 

Furthermore, a translation could be a good hint in the examination. 
So input a translation for each example is strongly recommended. 

You can also edit the example in the internal example format which is
part1 _keyword_ part2|translation
"_"(under bar) is the definition symbol of keywords. Whitespaces can 
be included in a keyword. 
'''
        wx.MessageBox(message, 'Help', wx.OK|wx.ICON_INFORMATION)
        
    def OnButton_markKeyword(self, evt):
        print 'on button mark keyword'
        selFrom, selTo = self.exampleText.GetSelection()
        text = self.exampleText.GetValue()
        f, t = None, None
        for m in re.finditer(r'''([^\s,.!?:;"\(\)\[\]\{\}<>\|]+)''', text, re.UNICODE):
            if m.start() <= selFrom <= m.end():
                f = m.start()
            if m.start() <= selTo <= m.end():
                t = m.end()
            if f is not None and t is not None:
                break
        if f is None:
            f = 0
        if t is None:
            t = len(text)
            
        self.mark = [f, t]
        
        if t == len(text):
            self.exampleText.ChangeValue(text + ' ')
            if selFrom == selTo == t:
                self.exampleText.SetSelection(selFrom + 1, selTo + 1)
            else:
                self.exampleText.SetSelection(selFrom, selTo)
        
        self.updateFullExample()
        self.updateExampleTextStyle()
        self.exampleText.SetFocus()
        
    def OnText_exampleText(self, evt):
        print 'on text example text'
        text = self.exampleText.GetValue()
        l = len(text)
        selFrom, selTo = self.exampleText.GetSelection()
        if selFrom == selTo and not self.mark == [-1, -1]:
            cursor = selFrom
            dl = l - self.prelen
            if dl:
                precur = cursor - dl
                if precur <= self.mark[1]:
                    self.mark[1] += dl
                if precur <= self.mark[0]:
                    self.mark[0] += dl
        if not self.settingExStyle:
            self.updateExampleTextStyle()
            self.updateFullExample()
        self.prelen = l
        print self.mark
        
    def OnText_translationText(self, evt):
        print 'on text translation text'
        self.updateFullExample()
        # self.updateExampleTextStyle()
        
    def OnText_fullExampleText(self, evt):
        print 'on text full example text'
        self.processFullExample()
    
    def updateExampleTextStyle(self):
        print 'update example text style'
        text = self.exampleText.GetValue()
        font = self.exampleText.GetFont()
        self.settingExStyle = True
        self.exampleText.SetStyle(0, len(text), 
                                  wx.TextAttr(colText=self.exampleText.GetForegroundColour(), 
                                              colBack=self.exampleText.GetBackgroundColour(), 
                                              font=font))
        
        if self.mark != [-1, -1]:        
            f, t = self.mark
            font.SetUnderlined(True)
            self.exampleText.SetStyle(f, t, wx.TextAttr(font=font))
    
            font.SetUnderlined(False)
            self.exampleText.SetStyle(len(text), len(text), wx.TextAttr(font=font))
            
            self.exampleText.Refresh()
        
        self.settingExStyle = False
        print 'update style finish'
    
    def getInternalEnExample(self):
        en = self.exampleText.GetValue()
        if self.mark[0] >= 0 and self.mark[1] >= 0:
            return '%s_%s_%s' % (en[:self.mark[0]], en[self.mark[0]:self.mark[1]], en[self.mark[1]:])
        else:
            return en
    
    def updateFullExample(self):
        englishPart = self.getInternalEnExample()
        translationPart = self.translationText.GetValue()
        self.fullExampleText.ChangeValue(englishPart + '|' + translationPart)
        self.processFullExample(False)
        
    def processFullExample(self, fromInput=True):
        print 'begin full process', self.mark
        text = self.fullExampleText.GetValue()
        try:
            self.example.importExample(text)
        except Exception, e:
            print e
            self.setFormatErrorStyle(True)
            if fromInput:
                self.mark = [-1, -1]
                parts = text.split('|', 1)
                self.exampleText.ChangeValue(parts[0])
                self.updateExampleTextStyle()
                if len(parts) > 1:
                    self.translationText.ChangeValue(parts[1])
        else:
            if self.example.translation:
                self.setFormatErrorStyle(None)
                if fromInput:
                    self.translationText.ChangeValue(self.example.translation)
            else:
                self.setFormatErrorStyle(False)
                if fromInput:
                    self.translationText.ChangeValue('')
            if fromInput:
                self.mark = [len(self.example.front) + 1, len(self.example.front) + len(self.example.answer) + 1]
                print 'In full process', self.mark
                print self.example.originalPart()
                self.exampleText.ChangeValue(self.example.originalPart())
                self.updateExampleTextStyle()

    def setFormatErrorStyle(self, error=None):
        if error is None:
            self.ExampleFormatErrorBar.Show(False)
            textColor = self.exampleText.GetBackgroundColour()
        else:
            errorMsg = 'ATTENTION: There is no keyword for this example. Click this for more information. '
            warnMsg = 'ATTENTION: There is no translation for this example. '
            message = errorMsg if error else warnMsg
            color = wx.NamedColor('red') if error else wx.NamedColor('yellow')
            bgColor = wx.NamedColor('yellow') if error else wx.NamedColor('blue')
            textColor = wx.NamedColor('red') if error else wx.NamedColor('yellow')
            self.ExampleFormatErrorBar.SetLabel(message)
            self.ExampleFormatErrorBar.SetForegroundColour(color)
            self.ExampleFormatErrorBar.SetBackgroundColour(bgColor)
            self.ExampleFormatErrorBar.Show(True)
        self.fullExampleText.SetBackgroundColour(textColor)
        self.fullExampleText.Refresh()
        self.internalFormatPanel.GetSizer().Layout()
        self.ExampleFormatErrorBar.Refresh()
        
        
class ExampleEditorDialog(wx.Dialog):
    
    def __init__(
            self, parent, ID, title, 
            style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER,
            ):
        '''
        Constructor
        '''
        
        wx.Dialog.__init__(self, parent, ID, title, style=style)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.panel = ExampleEditorPanel(self)
        sizer.Add(self.panel, proportion=1, flag=wx.ALL|wx.EXPAND, border=5)
        
        btnsizer = wx.StdDialogButtonSizer()
        btn = wx.Button(self, wx.ID_OK)
        btn.SetDefault()
        btnsizer.AddButton(btn)
        self.Bind(wx.EVT_BUTTON, self.OnButton_Ok, source=btn)
        
        btn = wx.Button(self, wx.ID_CANCEL)
        btnsizer.AddButton(btn)
        
        btnsizer.Realize()
        
        sizer.Add(btnsizer, proportion=0, flag=wx.EXPAND|wx.ALL, border=5)
        
        self.SetSizer(sizer)
        sizer.Fit(self)
        
    def __initEvent(self):
        self.Bind(wx.EVT_BUTTON, self.OnButton_Ok, id=wx.ID_OK)
        
    def OnButton_Ok(self, evt):
        print 'OK button' 
        if self.getExample():
            self.EndModal(wx.ID_OK)
        else:
            wx.MessageBox('Example format error or no example. \nPlease finish your editing.', 
                          'Error', wx.OK|wx.ICON_ERROR)
    
    def getExample(self):
        return self.panel.example
    
    def setExample(self, example):
        self.panel.fullExampleText.SetValue(unicode(example))
    